home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
src
/
dothrow.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-24
|
21KB
|
809 lines
/* SCCS Id: @(#)dothrow.c 3.1 92/12/10 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
/* Contains code for 't' (throw) */
#include "hack.h"
static void FDECL(hitfloor, (struct obj *));
static int FDECL(gem_accept, (struct monst *, struct obj *));
static int FDECL(throw_gold, (struct obj *));
static void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
static const char NEARDATA toss_objs[] =
{ ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
extern boolean notonhead; /* for long worms */
int
dothrow()
{
register struct obj *obj;
if(check_capacity(NULL)) return(0);
obj = getobj(toss_objs, "throw");
/* it is also possible to throw food */
/* (or jewels, or iron balls... ) */
if(!obj || !getdir(NULL)) { /* ask "in what direction?" */
if (obj && obj->oclass == GOLD_CLASS) {
u.ugold += obj->quan;
flags.botl = 1;
dealloc_obj(obj);
}
return(0);
}
if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
if(!canletgo(obj,"throw"))
return(0);
if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
You("must be wielding %s in order to throw it.", xname(obj));
return(0);
}
if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) != 125)
|| (obj->otyp == BOULDER
#ifdef POLYSELF
&& !throws_rocks(uasmon)
#endif
)) {
pline("It's too heavy.");
return(1);
}
if(!u.dx && !u.dy && !u.dz) {
You("cannot throw an object at yourself.");
return(0);
}
u_wipe_engr(2);
if(obj == uwep) {
if(welded(obj)) {
weldmsg(obj, FALSE);
return(1);
}
if(obj->quan > 1L)
setuwep(splitobj(obj, 1L));
else {
setuwep((struct obj *)0);
if (uwep) return(1); /* unwielded, died, rewielded */
}
}
else if(obj->quan > 1L)
(void) splitobj(obj, 1L);
freeinv(obj);
return(throwit(obj));
}
static void
hitfloor(obj)
register struct obj *obj;
{
if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
dropy(obj);
if(*u.ushops)
check_shop_obj(obj, obj->ox, obj->oy, FALSE);
return;
}
if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj);
else
pline("%s hits the floor.", Doname2(obj));
if (breaks(obj, TRUE)) return;
else if(obj->oclass == POTION_CLASS) {
pline("The flask breaks, and you smell a peculiar odor...");
potionbreathe(obj);
if(*u.ushops)
check_shop_obj(obj, u.ux, u.uy, TRUE);
obfree(obj, (struct obj *)0);
} else {
if(ship_object(obj, u.ux, u.uy, FALSE))
return;
dropy(obj);
if(*u.ushops)
check_shop_obj(obj, obj->ox, obj->oy, FALSE);
}
}
/*
* The player moves through the air for a few squares as a result of
* throwing or kicking something. To simplify matters, bumping into monsters
* won't cause damage but will wake them and make them angry.
* Auto-pickup isn't done, since you don't have control over your movements
* at the time.
* dx and dy should be the direction of the hurtle, not of the original
* kick or throw.
*/
void
hurtle(dx, dy, range)
int dx, dy, range;
{
register struct monst *mon;
struct obj *obj;
int nx, ny;
if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
nomul(-range);
You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
while(range--) {
nx = u.ux + dx;
ny = u.uy + dy;
if(!isok(nx,ny)) break;
if(IS_ROCK(levl[nx][ny].typ) || closed_door(nx,ny)) {
pline("Ouch!");
losehp(rnd(2+range), IS_ROCK(levl[nx][ny].typ) ?
"bumping to a wall" : "bumping into a door", KILLED_BY);
break;
}
if (obj = sobj_at(BOULDER,nx,ny)) {
You("bump into a %s. Ouch!", xname(obj));
losehp(rnd(2+range), "bumping to a boulder", KILLED_BY);
break;
}
u.ux = nx;
u.uy = ny;
newsym(u.ux - dx, u.uy - dy);
if(mon = m_at(u.ux, u.uy)) {
You("bump into %s.", a_monnam(mon));
wakeup(mon);
if(Is_airlevel(&u.uz))
mnexto(mon);
else {
/* sorry, not ricochets */
u.ux -= dx;
u.uy -= dy;
}
range = 0;
}
newsym(u.ux, u.uy);
if(range) {
flush_screen(1);
delay_output();
}
}
}
static void
check_shop_obj(obj, x, y, broken)
register struct obj *obj;
register xchar x, y;
register boolean broken;
{
register struct monst *shkp =
shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
if(!shkp) return;
if(!inside_shop(u.ux, u.uy)) return;
if(broken) {
if(obj->unpaid) {
(void)stolen_value(obj, u.ux, u.uy,
(shkp && shkp->mpeaceful), FALSE);
subfrombill(obj, shkp);
}
return;
}
if(!costly_spot(x, y) ||
*in_rooms(u.ux, u.uy, 0) != *in_rooms(x, y, 0)) {
if(!inside_shop(x, y) && obj->unpaid) {
(void)stolen_value(obj, u.ux, u.uy,
(shkp && shkp->mpeaceful), FALSE);
subfrombill(obj, shkp);
}
} else
if(costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
if(obj->unpaid) subfrombill(obj, shkp);
else if(!(x == shkp->mx && y == shkp->my))
sellobj(obj, x, y);
}
}
int
throwit(obj)
register struct obj *obj;
{
register struct monst *mon;
register int range, urange;
boolean impaired = (Confusion || Stunned || Blind ||
Hallucination || Fumbling);
int do_death = 0;
if (obj->cursed && (u.dx || u.dy) && !rn2(7)) {
boolean slipok = TRUE;
if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
&& uwep && (objects[obj->otyp].w_propellor > 0) &&
(objects[obj->otyp].w_propellor ==
-objects[uwep->otyp].w_propellor))
pline("The %s misfires!", xname(obj));
else {
/* only slip if it's meant to be thrown */
if((obj->otyp >= DART && obj->otyp <= JAVELIN) ||
(obj->otyp >= DAGGER && obj->otyp <= CRYSKNIFE &&
obj->otyp != ATHAME) || obj->otyp == WAR_HAMMER)
pline("The %s slips as you throw it!", xname(obj));
else slipok = FALSE;
}
if (slipok) {
u.dx = rn2(3)-1;
u.dy = rn2(3)-1;
if (!u.dx && !u.dy) u.dz = 1;
impaired = TRUE;
}
}
if(u.uswallow) {
mon = u.ustuck;
bhitpos.x = mon->mx;
bhitpos.y = mon->my;
} else if(u.dz) {
if (u.dz < 0 && pl_character[0] == 'V' &&
obj->oartifact == ART_MJOLLNIR && !impaired) {
pline("%s hits the ceiling and returns to your hand!",
The(xname(obj)));
obj = addinv(obj);
setuwep(obj);
return(1);
}
if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
pline("%s hits the ceiling, then falls back on top of your %s.",
Doname2(obj), /* note: obj->quan == 1 */
body_part(HEAD));
if(obj->oclass == POTION_CLASS)
potionhit(&youmonst, obj);
else {
int dmg = rnd((int)(obj->owt));
if (uarmh) {
if(is_metallic(uarmh)) {
pline("Fortunately, you are wearing a hard helmet.");
dmg = 1;
} else if (flags.verbose)
Your("%s does not protect you.", xname(uarmh));
} else if (obj->otyp == CORPSE &&
obj->corpsenm == PM_COCKATRICE) {
#ifdef POLYSELF
if(!resists_ston(uasmon))
if(!(poly_when_stoned(uasmon) &&
polymon(PM_STONE_GOLEM))) {
#endif
killer = doname(obj);
You("turn to stone.");
do_death = STONING;
#ifdef POLYSELF
}
#endif
}
if (!breaks(obj, TRUE)) {
if(!ship_object(obj, u.ux, u.uy, FALSE)) {
dropy(obj);
if(*u.ushops)
check_shop_obj(obj, obj->ox, obj->oy, FALSE);
}
}
if (do_death == STONING)
done(STONING);
else
losehp(dmg, "falling object", KILLED_BY_AN);
}
} else hitfloor(obj);
return(1);
} else if(obj->otyp == BOOMERANG && !Underwater) {
if(Is_airlevel(&u.uz) || Levitation) hurtle(-u.dx, -u.dy, 1);
mon = boomhit(u.dx, u.dy);
if(mon == &youmonst) { /* the thing was caught */
exercise(A_DEX, TRUE);
(void) addinv(obj);
return(1);
}
} else {
urange = (int)(ACURRSTR)/2;
range = urange - (int)(obj->owt/40);
if (obj == uball) {
if (u.ustuck) range = 1;
else if (range >= 5) range = 5;
}
if (range < 1) range = 1;
if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
&& uwep && objects[obj->otyp].w_propellor) {
if (objects[obj->otyp].w_propellor ==
-objects[uwep->otyp].w_propellor)
range++;
else
range /= 2;
}
if (Is_airlevel(&u.uz) || Levitation) {
/* action, reaction... */
urange -= range;
if(urange < 1) urange = 1;
range -= urange;
if(range < 1) range = 1;
}
#ifdef POLYSELF
if (obj->otyp == BOULDER) range = 20;
#endif
if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
range = 1;
if (Underwater) range = 1;
mon = bhit(u.dx,u.dy,range,THROWN_WEAPON,
(int (*)()) 0,(int (*)()) 0,obj);
/* have to do this after bhit() so u.ux & u.uy are correct */
if(Is_airlevel(&u.uz) || Levitation)
hurtle(-u.dx, -u.dy, urange);
}
if(mon) {
if(mon->isshk && (!inside_shop(u.ux, u.uy) ||
!index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops))) {
if(obj->otyp == PICK_AXE) {
register struct obj *otmp;
/* check if the pick axe was caught through */
/* a successful call to shkcatch() in bhit() */
for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
if (otmp == obj) return(1);
}
wakeup(mon);
hot_pursuit(mon);
}
(void) snuff_candle(obj);
/* awake monster if sleeping */
wakeup(mon);
notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
if(thitmonst(mon, obj)) return(1);
}
if(!u.uswallow) {
/* the code following might become part of dropy() */
int obj_glyph = obj_to_glyph(obj);
boolean gone = FALSE;
if (obj->oartifact == ART_MJOLLNIR && pl_character[0] == 'V') {
/* we must be wearing Gauntlets of Power to get here */
int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
tmp_at(DISP_FLASH, obj_glyph);
while(x != u.ux || y != u.uy) {
tmp_at(x, y);
delay_output();
x -= u.dx; y -= u.dy;
}
tmp_at(DISP_END, 0);
if(!impaired) {
pline("%s returns to your hand!", The(xname(obj)));
obj = addinv(obj);
setuwep(obj);
if(cansee(bhitpos.x, bhitpos.y))
newsym(bhitpos.x,bhitpos.y);
} else {
int dmg = rnd(4);
if (Blind)
pline("%s hits your %s!",
The(xname(obj)), body_part(ARM));
else
pline("%s flies back toward you, hitting your %s!",
The(xname(obj)), body_part(ARM));
(void) artifact_hit((struct monst *) 0, &youmonst,
obj, &dmg, 0);
losehp(dmg, xname(obj), KILLED_BY);
if(ship_object(obj, u.ux, u.uy, FALSE))
return (1);
dropy(obj);
}
return (1);
}
if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && !u.uinwater &&
obj->oclass == POTION_CLASS && rn2(2)) {
if(distu(bhitpos.x, bhitpos.y) < 3 && rn2(5)) {
pline("The flask breaks, and you smell a peculiar odor...");
potionbreathe(obj);
} else if(!Blind)
pline("The flask breaks.");
else pline("Crash!");
if(*u.ushops)
check_shop_obj(obj, bhitpos.x, bhitpos.y, TRUE);
obfree(obj, (struct obj *)0);
gone = TRUE;
}
if (gone || (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
breaks(obj, TRUE))) {
tmp_at(DISP_FLASH, obj_glyph);
tmp_at(bhitpos.x, bhitpos.y);
delay_output();
tmp_at(DISP_END, 0);
return(1);
}
if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
if(obj->otyp == CRYSKNIFE)
obj->otyp = WORM_TOOTH;
if(mon && mon->isshk && obj->otyp == PICK_AXE) {
mpickobj(mon, obj);
if(*u.ushops)
check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
return(1);
}
(void) snuff_candle(obj);
if(!mon && obj != uball) {
if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
return(1);
}
obj->nobj = fobj;
fobj = obj;
place_object(obj, bhitpos.x, bhitpos.y);
if(*u.ushops && obj != uball)
check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
stackobj(obj);
if (obj == uball) drop_ball(bhitpos.x, bhitpos.y);
if(cansee(bhitpos.x, bhitpos.y)) newsym(bhitpos.x,bhitpos.y);
} else {
/* ball is not picked up by monster */
if (obj != uball) mpickobj(u.ustuck,obj);
}
return(1);
}
int
thitmonst(mon, obj)
register struct monst *mon;
register struct obj *obj;
{
register int tmp; /* Base chance to hit */
register int disttmp; /* distance modifier */
/* Differences from melee weapons:
*
* Dex still gives a bonus, but strength does not.
* Polymorphed players lacking attacks may still throw.
* There's a base -1 to hit.
* No bonuses for fleeing or stunned targets (they don't dodge
* melee blows as readily, but dodging arrows is hard anyway).
* Not affected by traps, etc.
* Certain items which don't in themselves do damage ignore tmp.
* Distance and monster size affect chance to hit.
*/
tmp = -1 + Luck + find_mac(mon);
#ifdef POLYSELF
if (u.umonnum >= 0) tmp += uasmon->mlevel;
else
#endif
tmp += u.ulevel;
if(ACURR(A_DEX) < 4) tmp -= 3;
else if(ACURR(A_DEX) < 6) tmp -= 2;
else if(ACURR(A_DEX) < 8) tmp -= 1;
else if(ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
/* modify to-hit depending on distance; but keep it sane */
disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
if(disttmp < -4) disttmp = -4;
tmp += disttmp;
/* it's easier to hit a larger target */
if(bigmonst(mon->data)) tmp++;
if(mon->msleep) {
mon->msleep = 0;
tmp += 2;
}
if(!mon->mcanmove || !mon->data->mmove) {
tmp += 4;
if(!rn2(10)) {
mon->mcanmove = 1;
mon->mfrozen = 0;
}
}
if (is_orc(mon->data) && pl_character[0]=='E') tmp++;
if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */
if(obj->oclass == GEM_CLASS && mon->data->mlet == S_UNICORN) {
if (mon->mtame) {
pline("%s catches and drops %s.",
Monnam(mon), the(xname(obj)));
return(0);
} else {
pline("%s catches %s.", Monnam(mon), the(xname(obj)));
return(gem_accept(mon, obj));
}
}
if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
obj->otyp == UNICORN_HORN || obj->oclass == GEM_CLASS) {
if(obj->otyp < DART || obj->oclass == GEM_CLASS) {
if (!uwep ||
objects[obj->otyp].w_propellor !=
-objects[uwep->otyp].w_propellor) {
tmp -= 4;
} else {
tmp += uwep->spe - uwep->oeroded;
/*
* Elves and Samurais are highly trained w/bows,
* especially their own special types of bow.
* Polymorphing won't make you a bow expert.
*/
if ((pl_character[0] == 'E' || pl_character[0] == 'S')
&& -objects[uwep->otyp].w_propellor == WP_BOW)
tmp++;
if (pl_character[0] == 'E' && uwep->otyp == ELVEN_BOW)
tmp++;
if (pl_character[0] == 'S' && uwep->otyp == YUMI)
tmp++;
}
} else if(obj->otyp == BOOMERANG) tmp += 4;
tmp += obj->spe;
tmp += hitval(obj, mon->data);
if(tmp >= rnd(20)) {
if(hmon(mon,obj,1)){
/* mon still alive */
cutworm(mon, bhitpos.x, bhitpos.y, obj);
}
exercise(A_DEX, TRUE);
/* projectiles thrown disappear sometimes */
if((obj->otyp < BOOMERANG || obj->oclass == GEM_CLASS)
&& rn2(3)) {
if(*u.ushops)
check_shop_obj(obj, bhitpos.x,
bhitpos.y, TRUE);
/* check bill; free */
obfree(obj, (struct obj *)0);
return(1);
}
} else miss(xname(obj), mon);
} else if(obj->otyp == HEAVY_IRON_BALL) {
if(obj != uball) tmp += 2;
exercise(A_STR, TRUE);
if(tmp >= rnd(20)) {
(void) hmon(mon,obj,1);
exercise(A_DEX, TRUE);
} else miss(xname(obj), mon);
} else if (obj->otyp == BOULDER) {
tmp += 6; /* Likely to hit! */
exercise(A_STR, TRUE);
if(tmp >= rnd(20)) {
(void) hmon(mon,obj,1);
exercise(A_DEX, TRUE);
} else miss(xname(obj), mon);
} else if((obj->otyp == CREAM_PIE
#ifdef POLYSELF
|| obj->otyp == BLINDING_VENOM
#endif
) && ACURR(A_DEX) >= rnd(10)) {
(void) hmon(mon,obj,1); /* can't die from it */
#ifdef POLYSELF
} else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) {
(void) hmon(mon,obj,1);
#endif
} else if(obj->oclass == POTION_CLASS && ACURR(A_DEX) >= rnd(15)) {
potionhit(mon, obj);
return(1);
} else {
pline("%s misses %s.", The(xname(obj)), mon_nam(mon));
if(obj->oclass == FOOD_CLASS && is_domestic(mon->data))
if(tamedog(mon,obj)) return(1);
}
return(0);
}
static int
gem_accept(mon, obj)
register struct monst *mon;
register struct obj *obj;
{
char buf[BUFSZ];
boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
int ret = 0;
static const char NEARDATA nogood[] = " is not interested in your junk.";
static const char NEARDATA acceptgift[] = " accepts your gift.";
static const char NEARDATA maybeluck[] = " hesitatingly";
static const char NEARDATA noluck[] = " graciously";
static const char NEARDATA addluck[] = " gratefully";
Strcpy(buf,Monnam(mon));
mon->mpeaceful = 1;
/* object properly identified */
if(obj->dknown && objects[obj->otyp].oc_name_known) {
if(is_gem) {
if(is_buddy) {
Strcat(buf,addluck);
change_luck(5);
} else {
Strcat(buf,maybeluck);
change_luck(rn2(7)-3);
}
} else {
Strcat(buf,nogood);
goto nopick;
}
/* making guesses */
} else if(obj->onamelth || objects[obj->otyp].oc_uname) {
if(is_gem) {
if(is_buddy) {
Strcat(buf,addluck);
change_luck(2);
} else {
Strcat(buf,maybeluck);
change_luck(rn2(3)-1);
}
} else {
Strcat(buf,nogood);
goto nopick;
}
/* value completely unknown to @ */
} else {
if(is_gem) {
if(is_buddy) {
Strcat(buf,addluck);
change_luck(1);
} else {
Strcat(buf,maybeluck);
change_luck(rn2(3)-1);
}
} else {
Strcat(buf,noluck);
}
}
Strcat(buf,acceptgift);
mpickobj(mon, obj);
if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
ret = 1;
nopick:
if(!Blind) pline(buf);
rloc(mon);
return(ret);
}
/* returns 0 if object doesn't break */
/* returns 1 if object broke */
int
breaks(obj, loose)
register struct obj *obj;
register boolean loose; /* if not loose, obj is in fobj chain */
{
switch(obj->otyp) {
case MIRROR:
change_luck(-2); /* and fall through */
case CRYSTAL_BALL:
#ifdef TOURIST
case EXPENSIVE_CAMERA:
#endif
if(!Blind)
pline("%s shatters into a thousand pieces!",
Doname2(obj));
else You("hear something shatter!");
break;
case EGG:
pline("Splat!");
break;
case CREAM_PIE:
pline("What a mess!");
break;
case ACID_VENOM:
case BLINDING_VENOM:
pline("Splash!");
break;
default:
return 0;
}
/* it is currently assumed that 'loose' is co-extensive
* with 'thrown'. if this changes, an explicit 'thrown'
* arg must be added to breaks() to ensure proper
* treatment of shop objs.
*/
if(loose) {
newsym(obj->ox,obj->oy);
if(*u.ushops)
check_shop_obj(obj, obj->ox, obj->oy, TRUE);
obfree(obj, (struct obj *)0);
} else {
/* it is assumed that the obj is a floor-object */
register struct monst *shkp;
boolean costly, insider;
long loss = 0L;
#ifdef GCC_WARN
shkp = (struct monst *) 0;
#endif
costly = (costly_spot(obj->ox, obj->oy) &&
(shkp = shop_keeper(*in_rooms(obj->ox,
obj->oy, SHOPBASE))) != (struct monst *)0);
insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
*in_rooms(obj->ox, obj->oy, SHOPBASE) == *u.ushops);
if(costly)
loss = stolen_value(obj, u.ux, u.uy,
(shkp && shkp->mpeaceful), FALSE);
if(loss && !insider)
make_angry_shk(shkp, obj->ox, obj->oy);
delobj(obj);
}
return(1);
}
/*
* Note that the gold object is *not* attached to the fobj chain.
*/
static int
throw_gold(obj)
struct obj *obj;
{
int range, odx, ody;
long zorks = obj->quan;
register struct monst *mon;
if(u.uswallow) {
pline(is_animal(u.ustuck->data) ?
"%s in the %s's entrails." : "%s into %s.",
"The gold disappears", mon_nam(u.ustuck));
u.ustuck->mgold += zorks;
dealloc_obj(obj);
return(1);
}
if(u.dz) {
if(u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
pline("The gold hits the ceiling, then falls back on top of your %s.",
body_part(HEAD));
/* some self damage? */
if(uarmh) pline("Fortunately, you are wearing a helmet!");
}
if(flooreffects(obj,u.ux,u.uy,"fall")) return(1);
if(u.dz > 0) pline("The gold hits the floor.");
obj->nobj = fobj; /* add the gold to the object list */
fobj = obj;
place_object(obj,u.ux,u.uy);
if(*u.ushops) sellobj(obj, u.ux, u.uy);
stackobj(obj);
newsym(u.ux,u.uy);
return 1;
}
/* consistent with range for normal objects */
range = (int)((ACURRSTR)/2 - obj->owt/40);
/* see if the gold has a place to move into */
odx = u.ux + u.dx;
ody = u.uy + u.dy;
if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
bhitpos.x = u.ux;
bhitpos.y = u.uy;
} else {
mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
(int (*)()) 0, (int (*)()) 0, obj);
if(mon) {
if (ghitm(mon, obj)) /* was it caught? */
return 1;
} else {
if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
return 1;
}
}
if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
obj->nobj = fobj; /* add the gold to the object list */
fobj = obj;
place_object(obj,bhitpos.x,bhitpos.y);
if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
stackobj(obj);
newsym(bhitpos.x,bhitpos.y);
return(1);
}
/*dothrow.c*/